package com.gonsin.ta.logic.node;

import cn.hutool.core.util.ObjectUtil;
import com.gonsin.ta.logic.TA;
import com.gonsin.ta.logic.enums.NodeTypeEnum;
import com.gonsin.ta.logic.exceptions.ChainEndException;
import com.gonsin.ta.logic.exceptions.TaException;
import com.gonsin.ta.logic.parse.condition.context.ChainContextImpl;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class SpringNode extends Node {

    private NodeComponentProxy instance;

    private NodeTypeEnum nodeType;

    public SpringNode(NodeComponentProxy nodeComponent) {
        super(nodeComponent.getNodeId());
        this.instance = nodeComponent;
        nodeComponent.setNode(this);
    }

    @Override
    public void execute(ChainContextImpl context) throws Exception {
        if (ObjectUtil.isNull(instance)) {
            throw new TaException("未找到【{}】的组件", getNodeId());
        }

        if (instance.isAccess()) {
            //根据配置判断是否打印执行中的日志
            if (TA.LOG){
                TA.log().info("TA - 执行【{}】", getNodeId());
            }

            //这里开始进行重试的逻辑和主逻辑的运行
//            NodeExecutor nodeExecutor = NodeExecutorHelper.loadInstance().buildNodeExecutor(instance.getNodeExecutorClass());
            NodeExecutor nodeExecutor = new DefaultNodeExecutor();
            // 调用节点执行器进行执行
            try {
                nodeExecutor.execute(instance, context);
            } catch (Exception ex) {
                if (TA.LOG){
                    TA.log().info("TA - 执行【{}】错误", getNodeId());
                }
                throw ex;
            }
            //如果组件覆盖了isEnd方法，或者在在逻辑中主要调用了setEnd(true)的话，流程就会立马结束
            if (instance.isEnd() || context.isEnd()) {
                if(TA.LOG){
                    TA.log().info("TA - 从节点【{}】中结束", getNodeId());
                }
                throw new ChainEndException();
            }
            if (TA.LOG){
                TA.log().info("TA - 执行【{}】成功", getNodeId());
            }
        } else {
            if(TA.LOG){
                TA.log().info("TA - 跳过了【{}】节点执行", getNodeId());
            }
        }
    }

    public NodeTypeEnum getNodeType(){
        return nodeType;
    }


    public void setNodeType(NodeTypeEnum nodeType){
        this.nodeType = nodeType;
    }
}
